home *** CD-ROM | disk | FTP | other *** search
- /***************************************************
- **
- ** DN3DString.m
- **
- ** By Brian Hobbs (brian@ny.shl.com)
- **
- ** This class actually creates the 3D text string.
- ** It's performed through the PSW_tracestring call.
- ** The rest of the algorithm is massaging the bezier
- ** control points into the proper format to be
- ** recognized by RiPatchMesh, which physically
- ** creates the text in Renderman.
- **
- ** This code is public domain. Feel free to use
- ** it in any way you wish. I'd like to see any
- ** changes you make, tho.
- **
- ****************************************************/
-
- #import "DN3DString.h"
- #import "CharPaths.h"
- #import <ri/ri.h>
-
- #define SCALE 100
-
- #define MOVETO -1000
- #define LINETO -2000
- #define CURVETO -3000
- #define CLOSE -4000
- #define EMPTY -5000
-
- @implementation DN3DString:N3DShape
-
- - init
- {
- int i;
- [super init];
-
- resolution[0] = 35;
- resolution[1] = 1;
-
- textFont = (char *)NXZoneMalloc([self zone], sizeof(char) * 256);
- for (i=0; i<256; i++)
- textFont[i] = 0;
-
- return self;
- }
-
- - setResolution:(float)newRes
- {
- resolution[0] = newRes;
- return self;
- }
-
- - setTextString:(const char *)aString andFont:(const char *)aFont
- {
- float pathStack[1000];
- int *numCurves, *counter;
- int i,j,k;
-
- for (i=0; i<1000; i++)
- pathStack[i] = EMPTY;
-
- PSW_tracestring(aString, aFont, &(pathStack[0]));
-
- if (mesh){
- for (i=0; i<numPaths; i++)
- NXZoneFree([self zone], mesh[i]);
- NXZoneFree([self zone], mesh);
- }
- if (numCtrlPoints)
- NXZoneFree([self zone], numCtrlPoints);
-
- numPaths = i = 0;
-
- while (pathStack[i] != EMPTY){ // find the number of paths
- if (pathStack[i] == CLOSE)
- numPaths++;
- i++;
- }
-
- mesh = (RtFloat **)NXZoneMalloc([self zone], sizeof(RtFloat *) * numPaths);
- numCtrlPoints = (int *)NXZoneMalloc([self zone], sizeof(int) * numPaths);
- numCurves = (int *)NXZoneMalloc([self zone], sizeof(int) * numPaths);
- counter = (int *)NXZoneMalloc([self zone], sizeof(int) * numPaths);
-
- for (i=0; i<numPaths; i++){
- numCtrlPoints[i] = 0;
- numCurves[i] = 0;
- counter[i] = 0;
- }
-
- i = j = 0;
-
- // find the number of bezier control points of each path...
-
- while (pathStack[i] != EMPTY){
- if (pathStack[i] == LINETO || pathStack[i] == CURVETO)
- numCurves[j]++;
- if (pathStack[i] == CLOSE){
- numCtrlPoints[j] = (4 + ((numCurves[j] - 1) * 3));
- mesh[j] = (RtFloat *)NXZoneMalloc([self zone], sizeof(RtFloat) * (numCtrlPoints[j] * 2 * 3));
- j++;
- }
- i++;
- }
-
- j = 0;
-
- for (k = 0; k < 2; k++){
- i = j = 0;
- while ((pathStack[i] != EMPTY) && (j != numPaths)){ // then properly fill the mesh
- switch((int)pathStack[i]){
- case LINETO :
- mesh[j][counter[j]] = (float)pathStack[i-2] / SCALE;
- mesh[j][++counter[j]] = (float)pathStack[i-1] / SCALE;
- mesh[j][++counter[j]] = (float)k / 4.0;
- mesh[j][++counter[j]] = (float)pathStack[i-2] / SCALE;
- mesh[j][++counter[j]] = (float)pathStack[i-1] / SCALE;
- mesh[j][++counter[j]] = (float)k / 4.0;
- counter[j]++;
- break;
- case CLOSE :
- j++;
- break;
- case MOVETO:
- case CURVETO:
- break;
- default :
- mesh[j][counter[j]] = (float)pathStack[i] / SCALE;
- counter[j]++;
- if (((counter[j] + 1) % 3) == 0){
- mesh[j][counter[j]] = (float)k / 4.0;
- counter[j]++;
- }
- break;
- }
- i++;
- }
- }
-
- NXZoneFree([self zone], numCurves);
- NXZoneFree([self zone], counter);
-
- return self;
- }
-
- - setTextFont:(const char *)aFont
- {
- strcpy(textFont, (char *)aFont);
-
- return self;
- }
-
- - setTextString:(const char *)aString
- {
- // assumes setTextFont previously invoked
-
- [self setTextString:aString andFont:(const char *)textFont];
-
- return self;
- }
-
- - renderSelf:(RtToken)context
- {
- int i;
-
- RiBasis(RiBezierBasis, RI_BEZIERSTEP, RiBezierBasis, RI_BEZIERSTEP);
- RiGeometricApproximation( RI_TESSELATION, RI_PARAMETRIC, resolution, RI_NULL );
-
- // RiRotate(-90,1,0,0);
- RiTranslate(0,0,-0.5);
- RiScale(0.15, 0.15, 0.15);
-
- for (i=0; i<numPaths; i++)
- RiPatchMesh(RI_BILINEAR, (RtInt)numCtrlPoints[i], RI_PERIODIC, (RtInt)2, RI_NONPERIODIC, RI_P, (RtPointer)mesh[i], RI_NULL);
-
- return self;
- }
- @end
-
-